#include "qelib.h"



#define ARGP_LOG_DOMAIN      "argp-test"
#define argp_debug(...)      qelog_debug(ARGP_LOG_DOMAIN, __VA_ARGS__)
#define argp_info(...)       qelog_info(ARGP_LOG_DOMAIN, __VA_ARGS__)
#define argp_notice(...)     qelog_notice(ARGP_LOG_DOMAIN, __VA_ARGS__)
#define argp_warning(...)    qelog_warning(ARGP_LOG_DOMAIN, __VA_ARGS__)
#define argp_error(...)      qelog_error(ARGP_LOG_DOMAIN, __VA_ARGS__)



static qe_const_str usages[] = {
    "basic [options] [[--] args]",
    "basic [options]",
    QE_NULL,
};

static qe_ret action_string(qe_argparse *parser, qe_option *option)
{
    qe_str string = qe_option_string(option);
    argp_debug("action string:%s", string);
    return qe_yield;
}

static qe_ret action_integer(qe_argparse *parser, qe_option *option)
{
    qe_int integer = qe_option_integer(option);
    argp_debug("action integer:%d", integer);
    return qe_yield;
}

static qe_ret action_float(qe_argparse *parser, qe_option *option)
{
    qe_double vfloat = qe_option_float(option);
    argp_debug("action float:%f", vfloat);
    return qe_yield;
}

static qe_ret action_true(qe_argparse *parser, qe_option *option)
{
    qe_bool true = qe_option_boolean(option);
    argp_debug("action true:%d", true);
    return qe_yield;
}

static qe_ret action_false(qe_argparse *parser, qe_option *option)
{
    qe_bool false = qe_option_boolean(option);
    argp_debug("action false:%d", false);
    return qe_yield;
}

static qe_ret action_mask(qe_argparse *parser, qe_option *option)
{
    qe_u32 mask = qe_option_mask(option);
    argp_debug("action mask:0x%x", mask);
    return qe_yield;
}

static qe_ret action_unmask(qe_argparse *parser, qe_option *option)
{
    qe_u32 unmask = qe_option_mask(option);
    argp_debug("action unmask:0x%x", unmask);
    return qe_yield;
}

static qe_ret trace_cmd(qe_argparse *parser, qe_option *option)
{
    qe_int en;
    qe_int num;
    qe_int mode;
    qe_ret ret;
    qe_argparse subparser;

    qe_option options[] = {
        QE_OPT_INTEGER('e', "--enable", "trace enable", &en),
        QE_OPT_INTEGER('e', "--enable", "trace number", &num),
        QE_OPT_INTEGER('e', "--enable", "trace mode", &mode),
        QE_OPT_HELP('h', "--help", "trace help"),
        QE_OPT_END(),
    };

    qe_argp_init(&subparser, options, usages,
        "\ntrace command.", 
        "\ntrace command end.");
    ret = qe_argp_parse(&subparser, parser->argc, parser->argv);
    if (ret != qe_ok) {
        return qe_yield;
    }

    argp_debug("en:%d num:%d mode:%d", en, num, mode);

    return qe_yield;
}

int main(int argc, char *argv[])
{
    qe_ret ret;
    qe_str string = QE_NULL;
    qe_bool true_bool = qe_false;
    qe_bool false_bool = qe_true;
    qe_int integer = 0;
    qe_u32 mask = 0x0;
    qe_u32 unmask = 0x1;
    qe_double vfloat;
    qe_argparse parser;

    qelog_init(QELOG_DEBUG, QELOG_CL|QELOG_LV|QELOG_DM);

    qe_option options[] = {
        
        QE_OPT_GROUP("value test"),
        QE_OPT_STRING(QE_NULL, "val-str", "value string", &string),
        QE_OPT_TRUE(QE_NULL, "val-true", "value true", &true_bool),
        QE_OPT_FALSE(QE_NULL, "val-false", "value false", &false_bool),
        QE_OPT_INTEGER('n', "val-int", "value integer", &integer),
        QE_OPT_FLOAT('f', "val-float", "value float", &vfloat),
        QE_OPT_MASK(QE_NULL, "val-mask", "value bits mask", &mask, 0x1),
        QE_OPT_UNMASK(QE_NULL, "val-unmask", "value bits unmask", &unmask, 0x1),

        QE_OPT_GROUP("action test"),
        QE_ACT_STRING(QE_NULL, "act-str", "action string", 
            &string, QE_NULL, action_string),
        QE_ACT_INTEGER(QE_NULL, "act-int", "action integer", 
            &integer, QE_NULL, action_integer),
        QE_ACT_FLOAT(QE_NULL, "act-float", "action float", 
            &vfloat, QE_NULL, action_float),
        QE_ACT_TRUE(QE_NULL, "act-true", "action true",
            &true_bool, QE_NULL, action_true),
        QE_ACT_FALSE(QE_NULL, "act-false", "action false",
            &false_bool, QE_NULL, action_false),       
        QE_ACT_MASK(QE_NULL, "act-mask", "action mask",
            &mask, 0x1, action_mask),
        QE_ACT_UNMASK(QE_NULL, "act-unmask", "action unmask",
            &unmask, 0x1, action_unmask),

        QE_OPT_GROUP("subcmd test"),
        QE_OPT_SUBCMD("trace", "trace command", QE_NULL, trace_cmd),

        QE_OPT_HELP('h', "help", "Help message"),
        QE_OPT_END(),
    };

    qe_argp_init(&parser, options, usages,
        "\nA brief description of what the program does and how it works.", 
        "\nAdditional description of the program after the description of the arguments.");
    ret = qe_argp_parse(&parser, argc, (qe_const_str *)argv);
    if (ret != qe_ok) {
        return -1;
    }

    argp_debug("string  : %s", string);
    argp_debug("integer : %d", integer);
    argp_debug("float   : %f", vfloat);
    argp_debug("true    : %d", true_bool);
    argp_debug("false   : %d", false_bool);
    argp_debug("mask    : 0x%x", mask);
    argp_debug("unmask  : 0x%x", unmask);

    return 0;
}